package me.buick.util.jmeter.snmpprocessvisualizers;

import static javax.swing.SwingConstants.CENTER;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;

import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSeparator;

import me.buick.util.snmp.core.pojo.ProcessInfoPojo;

import org.apache.jmeter.visualizers.MonitorModel;

public class SNMPProcessCPUOverviewPanel extends SNMPProcessBorderedComponent {

	SNMPProcessPlotterPercentage plotter;

	static final Dimension PREFERRED_PLOTTER_SIZE = new Dimension(300, 200);
	static final Dimension MINIMUM_PLOTTER_SIZE = new Dimension(200, 150);

	Map<String, SNMPProcessPlotterPercentage.Sequence> seqStore = Collections.synchronizedMap(new HashMap<String, SNMPProcessPlotterPercentage.Sequence>());

	// This is the default view range for all the overview plotters
	static final int VIEW_RANGE = -1; // Show all data
	static final boolean IS_GTK = false;

	static Color PLOTTER_COLOR = IS_GTK ? new Color(231, 111, 80) : null;

	JLabel infoLabel;
	private SNMPProcessColorTemplates ct = new SNMPProcessColorTemplates();
	private AtomicBoolean initChecked = new AtomicBoolean(false);

	public SNMPProcessCPUOverviewPanel() {
		super("CPU Usage");
		setLayout(new BorderLayout(0, 0));

		SNMPProcessPlotterPercentage plotter = new SNMPProcessPlotterPercentage();
		plotter.setPreferredSize(PREFERRED_PLOTTER_SIZE);
		plotter.setMinimumSize(MINIMUM_PLOTTER_SIZE);
		plotter.setViewRange(VIEW_RANGE);
		plotter.setUnit(SNMPProcessPlotterPercentage.Unit.PERCENT);
		setPlotter(plotter);
	}

	public SNMPProcessPlotterPercentage getPlotter() {
		return this.plotter;
	}

	public void setPlotter(SNMPProcessPlotterPercentage plotter) {
		this.plotter = plotter;
		setComponent(plotter);
	}

	public void updateCPUInfo(MonitorModel result) {
		SNMPProcessMonitorModel snmpResult = (SNMPProcessMonitorModel) result;
		
		Map<Integer, ProcessInfoPojo> ppj = snmpResult.getProcessPerfPojos();
		
		
		// Start Overview Algorithm
		Map<String, ProcessInfoPojo> mapp = Collections.synchronizedMap(new HashMap<String, ProcessInfoPojo>());
		
		if(ppj != null && ppj.size() > 0){
			for(Integer key : ppj.keySet()){
				ProcessInfoPojo currentPojo = ppj.get(key);
				String procName = currentPojo.getProcName();
				ProcessInfoPojo storedPojo = mapp.get(procName);
				if(storedPojo == null){
					mapp.put(procName, currentPojo);
				}else{
					ProcessInfoPojo resultPojo = new ProcessInfoPojo(storedPojo.getPid(), storedPojo.getProcName(), storedPojo.getProcParameters(), storedPojo.getProcPath(),0, (storedPojo.getProcPerfMemKBytes()+currentPojo.getProcPerfMemKBytes()), currentPojo.getProcRunningStatus(), storedPojo.getProcType(), storedPojo.getCPUCores());
					mapp.remove(procName);
					resultPojo.setCPUPerc((storedPojo.getCPUPerc()+currentPojo.getCPUPerc())>1.00?1.00:(storedPojo.getCPUPerc()+currentPojo.getCPUPerc()));
					mapp.put(procName, resultPojo);
				}
			}
		}
		
		ppj = Collections.synchronizedMap(new HashMap<Integer, ProcessInfoPojo>());
		for(ProcessInfoPojo pi : mapp.values()){
			ppj.put(pi.getPid(), pi);
		}
		
		List<String> pnameList = new ArrayList<String>();
		for(String procName : this.seqStore.keySet()){
			ProcessInfoPojo tpj = mapp.get(procName);
			if(tpj == null){
				pnameList.add(procName);
			}
		}
		for(String procName : pnameList){
			this.seqStore.remove(procName);
			plotter.removeSequence(procName);
		}
		
		// End Overview Algorithm
		
		Map<String, Long> values = new HashMap<String, Long>();
		
		for(Integer pid : ppj.keySet()){
			ProcessInfoPojo ppojo = ppj.get(pid);
			String procName = ppojo.getProcName();
			SNMPProcessPlotterPercentage.Sequence tempSeq = this.seqStore.get(procName);
			if(tempSeq == null){
				tempSeq = plotter.createSequence(procName, "CPU Usage: "+ppojo.getProcName()+"/pid: "+ppojo.getPid(), ct.getColor(),true);
				this.seqStore.put(procName, tempSeq);
			}
			values.put(procName, (long)(ppj.get(pid).getCPUPerc()*100));
		}
		getPlotter().addValues(snmpResult.getTimestamp(), values);
	}

	public JLabel getInfoLabel() {
		if (infoLabel == null) {
			infoLabel = new JLabel("", CENTER) {
				@Override
				public void setText(String text) {
					if (text.startsWith("<html>")) {
						// Replace spaces with nbsp, except the
						// last one of two or more (to allow wrapping)
						StringBuilder buf = new StringBuilder();
						char[] chars = text.toCharArray();
						int n = chars.length;
						for (int i = 0; i < n; i++) {
							if (chars[i] == ' '
									&& ((i < n - 1 && chars[i + 1] == ' ') || ((i == 0 || chars[i - 1] != ' ') && (i == n - 1 || chars[i + 1] != ' ')))) {
								buf.append("&nbsp;");
							} else {
								buf.append(chars[i]);
							}
						}
						text = buf.toString();
					}
					super.setText(text);
				}
			};

			if (IS_GTK) {
				JPanel southPanel = new JPanel(new BorderLayout());
				JSeparator separator = new JSeparator(JSeparator.HORIZONTAL);
				southPanel.add(separator, BorderLayout.NORTH);
				southPanel.add(infoLabel, BorderLayout.SOUTH);
				add(southPanel, BorderLayout.SOUTH);
			} else {
				add(infoLabel, BorderLayout.SOUTH);
			}
		}
		return infoLabel;
	}

	public void clearData() {
		plotter.clearData();

		SNMPProcessPlotterPercentage plotter = new SNMPProcessPlotterPercentage();
		plotter.setPreferredSize(PREFERRED_PLOTTER_SIZE);
		plotter.setMinimumSize(MINIMUM_PLOTTER_SIZE);
		plotter.setViewRange(VIEW_RANGE);
		plotter.setUnit(SNMPProcessPlotterPercentage.Unit.PERCENT);
		setPlotter(plotter);
		this.seqStore.clear();
		ct.resetCounter();
	}

}
